﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
using System.Windows.Forms.DataVisualization.Charting;
using System.Collections;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar;

//串口参数结构体
struct COMPORT_ATTRIBUTE
{
    public int bandrate;
    public int data_bit;
    public Parity parity_check_bit;
    public StopBits stop_bit;
    public string comport_number;
};


namespace Drawer
{

    public partial class MainForm : AntdUI.Window
    {
        byte updata_USART = 0;
        int UsartUpdataCnt = 0;  
        int Pressure_val, Temperature_val, Pressure_adc = 0, Temperature_adc = 0;
        string Pressure_str, Temperature_str;
        byte P_unit, T_unit,usart_en;
        byte[] cod1 = new byte[7] { 0x5A, 0x5A, 0x03 , 0x01,0x01,0x01,0x06 };//serialPort1.Write(cod1, 0, 7);
        byte[] RxBuffer = new byte[50];
        byte[] ParseBuffer = new byte[50];
        byte Master_Header2 = 0x5A, Master_Header1 = 0xA5;
        byte last_ur_buf;
        byte RX_Count = 0;
        double[] Prebuff = new double[50];
        double[] Tempbuff = new double[50];
        // 串口参数
        private COMPORT_ATTRIBUTE uart_port;
        //实例化串口类
        public System.IO.Ports.SerialPort _serialPort = new System.IO.Ports.SerialPort();
        //============================== 定义线程 ===========================================
        Thread listenThread;
        public bool rx_thread_stop_flag = false;//线程停止标志
        public bool rx_thread_start_flag = false;//线程停止标志
        public MainForm()
        {
            InitializeComponent();
            InitializeSerialSet(); // 初始化串口设置
        }
        private void MainForm_Load(object sender, EventArgs e)
        {
            BuffInit();
            UsartUpdataCnt = 0;
            usart_en = 0;
            select2.SelectedIndex = 4;
            select3.SelectedIndex = 0;
            select4.SelectedIndex = 0;
        }
       /// <summary>
       /// 按键刷新串口
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            InitializePorts();
        }
        void BuffInit()
        {
            for (byte i = 0; i < Prebuff.Length; i++)
            {
                Prebuff[i] = 1001.25;
                Tempbuff[i] = 21.25;
            }
        }
        double GetPressureValue(int p,byte unit)
        {
            double Pressure_temp = 0;
            Pressure_temp = ((double)p / 100);//mbar
            switch(unit)
            {
                case 1://kpa
                    Pressure_temp = Pressure_temp / 10;
                    break;
                case 2://inhg
                    Pressure_temp = Pressure_temp * 29 / 1000;
                    break;
                case 3://mmhg
                    Pressure_temp = Pressure_temp * 75 / 100;
                    break;
            }
            return Pressure_temp;
        }
        double GetTemperatureValue(int t, byte unit)
        {
            double Temperature_temp = 0;
            Temperature_temp = ((double)t / 10) * (9 / (5 + 4 * (1 - unit))) + 32 * unit; //根据温度单位计算
            return Temperature_temp;
        }
        void ProcessingData()
        {
            double Temperature_temp, Pressure_temp;
            if (updata_USART == 1)
            {
                updata_USART = 0;

                if (++UsartUpdataCnt > 0xFFFFFF) UsartUpdataCnt = 0;
                label_log.Text = "Rx: " + UsartUpdataCnt.ToString();

                Pressure_temp = GetPressureValue(Pressure_val, P_unit);
                Temperature_temp = GetTemperatureValue(Temperature_val, T_unit);
                Temperature_str = Temperature_temp.ToString("f1");
                Pressure_str = Pressure_temp.ToString("f2");
                input1.Text = Pressure_str;
                input2.Text = Temperature_str;
                input3.Text = Pressure_adc.ToString();
                input4.Text = Temperature_adc.ToString();

                Array.Copy(Prebuff, 1, Prebuff, 0, Prebuff.Length - 1);
                Array.Copy(Tempbuff, 1, Tempbuff, 0, Tempbuff.Length - 1);
                Prebuff[Prebuff.Length - 1] = Pressure_temp;
                Tempbuff[Tempbuff.Length - 1] = Temperature_temp;
            }
            Chart1.Series[0].Points.DataBindY(Prebuff); //Array.Copy(Prebuff, 1, Prebuff, 0, Prebuff.Length - 1);
            Chart1.Series[1].Points.DataBindY(Tempbuff);
        }
        /// <summary>
        /// 测试期间使用定时器
        /// </summary>
        int CNT;
        private void timer1_Tick(object sender, EventArgs e)
        {
            ///测试 start
            updata_USART = 1;
            if (++CNT > 50)
            {
                CNT = 0;
                byte[] sendbuff = new byte[4] { 0x01, 0x02, 0x03, 0x04 };
                _serialPort.Write(sendbuff, 0, 4);
            }
            Pressure_val = 100123 + CNT * 500;
            Temperature_val = 123 + CNT * 10;
            ProcessingData();

            
            ///测试用 end
        }   
        /// <summary>
        /// 扫描串口
        /// </summary>
        public void InitializePorts()
        {
            string[] port_names = SerialPort.GetPortNames();
            string last_name = "";
            button1.Enabled = true;
            button2.Enabled = false;
            select1.Items.Clear();
            if (port_names == null)
            {
                MessageBox.Show("本机没有串口！", "Error");
                return;
            }
            foreach (string s in System.IO.Ports.SerialPort.GetPortNames())
            {
                select1.Items.Add(s);
                last_name = s;//保存最新的一个
            }
            select1.Text = last_name;
            if (last_name == "")
            {
                button1.Enabled = false;
            }
            uart_port.comport_number = last_name;//赋值变量
        }


        public void InitializeSerialSet()
        {

            // 初始化扫描串口
            InitializePorts();
            // 初始化波特率
            uart_port.bandrate = 115200;
            // 初始化数据位
            uart_port.data_bit = 8;
            // 初始化停止位
            uart_port.stop_bit = (StopBits)1;
            // 初始化校验位
            uart_port.parity_check_bit = 0;//Parity.None
            if (uart_port.parity_check_bit == (Parity)1)//  Parity.Odd
            {
            }
            else if (uart_port.parity_check_bit == (Parity)2) //Parity.Even
            {
            }
            else
            {
            }

        }
        /// <summary>
        /// 打开串口
        /// </summary>
        private bool OpenComport()
        {
            //打开串口
            if (_serialPort.IsOpen)
            {
                //关闭后重新打开
                CloseComport();
                if (_serialPort.IsOpen)//关闭失败
                {
                    return false;
                }

            }
            //串口设置
            _serialPort.PortName = select1.Text;            //串口名称
            _serialPort.BaudRate = Convert.ToInt32(select2.Text);       //波特率
            _serialPort.DataBits = uart_port.data_bit;      //数据位
            _serialPort.Parity = uart_port.parity_check_bit;//校验位
            _serialPort.StopBits = uart_port.stop_bit;      //停止位

            try
            {
                _serialPort.Open(); //打开串口
                                    //_serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);//串口接收处理函数
                RxThreadOnOff(true);//开启线程
            }
            catch
            {
                MessageBox.Show("串口打开失败！");
                return false;
            }
            return true;
        }
        /// <summary>
        /// 关闭串口
        /// </summary>
        private void CloseComport()
        {
            try
            {
                //关闭线程
                RxThreadOnOff(false);
                _serialPort.Close(); //关闭串口
            }
            catch
            {
                MessageBox.Show("串口关闭失败！");
            }
        }
        /// <summary>
        /// 开关接收线程
        /// </summary>
        private void RxThreadOnOff(bool on_off)
        {
            if (on_off)
            {
                listenThread = new Thread(() => ReceiveData());//开启一个线程来不断的接收数据
                listenThread.IsBackground = true;
                listenThread.Start();
            }
            else
            { 
                rx_thread_stop_flag = true;
                while (listenThread.IsAlive)//等待停止
                { }
                rx_thread_stop_flag = false;
            }
        }



        private void button_Click(object sender, EventArgs e)
        {
            try
            {
                usart_en = 0;
                CloseComport();
                button1.Enabled = true;
                button2.Enabled = false;
                button3.Enabled = true;

                UsartUpdataCnt = 0;
                com.BackColor = Color.White;
            }
            catch
            {

            }
        }

        private void titlebar_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            UsartUpdataCnt = 0;
            if (OpenComport())
            {
                _serialPort.Write(cod1, 0, 7);
                usart_en = 1;
                com.BackColor = Color.LimeGreen;
                button1.Enabled = false;
                button2.Enabled = true;
                button3.Enabled = false;
                _serialPort.Write(cod1, 0, 7);
            }
        }
        private void button3_Click_1(object sender, EventArgs e)
        {
            InitializePorts();
        }


        private void select4_SelectedIndexChanged(object sender, AntdUI.IntEventArgs e)
        {
            T_unit = (byte)select4.SelectedIndex;
            Chart1.ChartAreas[0].AxisY2.Maximum = 85 + 100 * T_unit;
            Chart1.ChartAreas[0].AxisY2.Title = "Temperature - " + select4.Items[T_unit];
            Array.Clear(Tempbuff, 0, Tempbuff.Length);
            Chart1.Series[1].Points.DataBindY(Tempbuff);
        }

        private void select3_SelectedIndexChanged(object sender, AntdUI.IntEventArgs e)
        {
            P_unit = (byte)select3.SelectedIndex;
            double Maximum_temp = 2000;
            switch (P_unit)
            {
                case 1://kpa
                    Maximum_temp = Maximum_temp / 10;
                    break;
                case 2://inhg
                    Maximum_temp = Maximum_temp * 29 / 1000;
                    break;
                case 3://mmhg
                    Maximum_temp = Maximum_temp * 75 / 100;
                    break;
            }
            Chart1.ChartAreas[0].AxisY.Maximum = Maximum_temp;
            Chart1.ChartAreas[0].AxisY.Title = "Pressure - " + select3.Items[P_unit];
            Array.Clear(Prebuff, 0, Prebuff.Length);
            Chart1.Series[0].Points.DataBindY(Prebuff);
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        public void ReceiveData()
        {
            //接收线程
            while (_serialPort.IsOpen && !rx_thread_stop_flag /*&& usart_en == 1*/)//线程循环
            {
                byte[] usartget_data = new byte[_serialPort.BytesToRead];                                //定义缓冲区，串口事件触发时收到多个字节
                _serialPort.Read(usartget_data, 0, usartget_data.Length);
                for (byte i = 0; i < usartget_data.Length; i++)
                {
                    Uart_Unpack(usartget_data[i]);
                }
            }
        }
        /// <summary>
        /// 数据解包
        /// </summary>
        /// <param name="len"></param>
        void UR_Data_ParseBuffer(byte len)
        {
            switch (ParseBuffer[1])
            {
                case 0:
                    break;
                case 1:
                    Pressure_val = ((ParseBuffer[2] << 24) | (ParseBuffer[3] << 16) | (ParseBuffer[4] << 8) | ParseBuffer[5]);
                    Pressure_adc = ((ParseBuffer[6] << 8) | ParseBuffer[7]);
                    Temperature_val = ((ParseBuffer[8] << 8) |ParseBuffer[9]);
                    Temperature_adc = ((ParseBuffer[10] << 8) | ParseBuffer[11]);
                    updata_USART = 1;
                    break;
                case 5:
                    Pressure_adc = ((ParseBuffer[2]<<8)| ParseBuffer[3]);
                    Temperature_adc = ((ParseBuffer[4]<<8) | ParseBuffer[5]);
                    updata_USART = 1;
                    break;
            }   
            if(updata_USART == 1)
            {
                updata_USART = 0;
                ProcessingData();
            }
        }
        /// <summary>
        ///  0xA55A + length(1byte) + DevAddr(1byte) + cmd(1byte) + data(1byte~50byte) + crc(1byte)
        ///  length = DevAddr + cmd + data
        ///  找到完整帧
        /// </summary>
        /// <param name="urbuf"></param>
        void Uart_Unpack(byte urbuf)
        {
            byte rxbuffer_length = 50;
            if (urbuf == Master_Header1 && last_ur_buf == Master_Header2)
            {
                RX_Count = 1;
                RxBuffer[0] = last_ur_buf;
            }
            last_ur_buf = urbuf;
            if (RX_Count > 0)
            {
                RxBuffer[RX_Count] = urbuf;
                if (RX_Count == 2) // length
                {
                    if (RxBuffer[2] > rxbuffer_length)
                    {
                        RX_Count = 0;
                        Array.Clear(RxBuffer, 0, rxbuffer_length);
                        return;
                    }
                }
                if (RX_Count >= RxBuffer[2] + 4)
                {
                    RX_Count = 0;
                   /* if (UartCheckAdd8((unsigned char *)RxBuffer + 2, RxBuffer[2] + 1) == 0)
                    {
                        memset(RxBuffer, 0, rxbuffer_length);
                        return;
                    }*/
                    Array.Copy(RxBuffer,3,ParseBuffer,0, RxBuffer[2]);
                    UR_Data_ParseBuffer(RxBuffer[2]);
                    Array.Clear(RxBuffer, 0, rxbuffer_length);
                    return;
                }
                RX_Count++;
            }
        }




    }
}
